package com.easy.generator.java;

import com.easy.generator.Easy;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.time.LocalDate;

/**
 * @author easy
 * @date 2025年07月05日 19:36
 */
public class InnerCaptchaGenerator {
    private static final String CLASS_NAME = "InnerCaptchaUtil";
    private static final String PACKAGE_NAME = Easy.UTIL_PACKAGE;
    private static final String MAP_NAME = "ExpiringMap";
    private static final String CONTROLLER_NAME = "CaptchaController";
    private static final String CLASS_TEMPLATE =
            "package " + PACKAGE_NAME + ";\n" +
                    "\n" +
                    "import cn.hutool.captcha.CaptchaUtil;\n" +
                    "import cn.hutool.captcha.LineCaptcha;\n" +
                    "\n" +
                    "import java.util.HashMap;\n" +
                    "import java.util.Map;\n" +
                    "import java.util.UUID;\n" +
                    "\n" +
                    "public class " + CLASS_NAME + " {\n" +
                    "    //计时Map 用户存储验证码 有效时间单位为秒\n" +
                    "    public static final ExpiringMap<String,String> captchaMap=new ExpiringMap<>(5*60*1000);\n" +
                    "\n" +
                    "    public static final LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(200, 100,4,5);\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 获取验证码的方法\n" +
                    "     * @return\n" +
                    "     */\n" +
                    "    public static Map getCaptcha(){\n" +
                    "        Map<String,String> result=new HashMap<>();\n" +
                    "        String key= UUID.randomUUID().toString();\n" +
                    "        lineCaptcha.createCode();\n" +
                    "        //验证码\n" +
                    "        String code=lineCaptcha.getCode();\n" +
                    "        //验证码图片base64\n" +
                    "        String base=lineCaptcha.getImageBase64();\n" +
                    "        result.put(\"key\",key);\n" +
                    "        result.put(\"base\",\"data:image/png;base64,\"+base);\n" +
                    "        captchaMap.put(key,code);\n" +
                    "        return result;\n" +
                    "    }\n" +
                    "\n" +
                    "    /**\n" +
                    "     * 验证码验证方法\n" +
                    "     * @param key\n" +
                    "     * @param code\n" +
                    "     * @return\n" +
                    "     */\n" +
                    "    public static boolean verifyCaptcha(String key,String code){\n" +
                    "        boolean hasKey=captchaMap.containsKey(key);\n" +
                    "        if(hasKey){\n" +
                    "            String captcha=captchaMap.get(key);\n" +
                    "            if(captcha.equalsIgnoreCase(code)){\n" +
                    "                captchaMap.remove(key);\n" +
                    "                return true;\n" +
                    "            }\n" +
                    "        }\n" +
                    "        return false;\n" +
                    "    }\n" +
                    "}\n";
    public static void generateUtil() throws IOException {
        String content = String.format(CLASS_TEMPLATE, LocalDate.now());
        File outputFile = new File(Easy.PROJECT_ABSOLUTE_URL + Easy.SRC_DIR + Easy.convertPackagePath(PACKAGE_NAME) + "/" + CLASS_NAME + ".java");
        try (FileWriter writer = new FileWriter(outputFile)) {
            writer.write(content);
        }
    }

    private static final String CLASS_TEMPLATE_MAP =
                    "package "+PACKAGE_NAME+";\n" +
                    "\n" +
                    "import java.util.*;\n" +
                    "import java.util.concurrent.*;\n" +
                    "\n" +
                    "public class "+MAP_NAME+"<K, V> {\n" +
                    "    private final Map<K, V> map = new HashMap<>();\n" +
                    "    private final Map<K, Long> expiryTimes = new HashMap<>();\n" +
                    "    private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();\n" +
                    "    private final long defaultExpiryMillis;\n" +
                    "\n" +
                    "    public "+MAP_NAME+"(long defaultExpiryMillis) {\n" +
                    "        this.defaultExpiryMillis = defaultExpiryMillis;\n" +
                    "        executor.scheduleAtFixedRate(this::cleanup, 1, 1, TimeUnit.SECONDS);\n" +
                    "    }\n" +
                    "\n" +
                    "    public void put(K key, V value) {\n" +
                    "        put(key, value, defaultExpiryMillis);\n" +
                    "    }\n" +
                    "\n" +
                    "    public void put(K key, V value, long expiryMillis) {\n" +
                    "        map.put(key, value);\n" +
                    "        expiryTimes.put(key, System.currentTimeMillis() + expiryMillis);\n" +
                    "    }\n" +
                    "\n" +
                    "    public V get(K key) {\n" +
                    "        if (!expiryTimes.containsKey(key) || expiryTimes.get(key) < System.currentTimeMillis()) {\n" +
                    "            remove(key);\n" +
                    "            return null;\n" +
                    "        }\n" +
                    "        return map.get(key);\n" +
                    "    }\n" +
                    "    public boolean containsKey(K key) {\n" +
                    "        return map.containsKey(key);\n" +
                    "    }\n" +
                    "\n" +
                    "    public void remove(K key) {\n" +
                    "        map.remove(key);\n" +
                    "        expiryTimes.remove(key);\n" +
                    "    }\n" +
                    "\n" +
                    "    private void cleanup() {\n" +
                    "        long now = System.currentTimeMillis();\n" +
                    "        expiryTimes.entrySet().removeIf(entry -> {\n" +
                    "            if (entry.getValue() < now) {\n" +
                    "                map.remove(entry.getKey());\n" +
                    "                return true;\n" +
                    "            }\n" +
                    "            return false;\n" +
                    "        });\n" +
                    "    }\n" +
                    "\n" +
                    "    public void shutdown() {\n" +
                    "        executor.shutdown();\n" +
                    "    }\n" +
                    "}\n";
    public static void generateMap() throws IOException {
        String content = String.format(CLASS_TEMPLATE_MAP, LocalDate.now());
        File outputFile = new File(Easy.PROJECT_ABSOLUTE_URL + Easy.SRC_DIR + Easy.convertPackagePath(PACKAGE_NAME) + "/" + MAP_NAME + ".java");
        try (FileWriter writer = new FileWriter(outputFile)) {
            writer.write(content);
        }
    }
    private static final String CLASS_TEMPLATE_CONTROLLER =
            "package "+ Easy.CONTROLLER_PACKAGE+";\n" +
                    "\n" +
                    "import "+ Easy.UTIL_PACKAGE+".InnerCaptchaUtil;\n" +
                    "import "+ Easy.UTIL_PACKAGE+".Result;\n" +
                    "import org.springframework.web.bind.annotation.*;\n" +
                    "\n" +
                    "@RestController\n" +
                    "@RequestMapping(\"/captcha\")\n" +
                    "@CrossOrigin\n" +
                    "public class CaptchaController {\n" +
                    "\n" +
                    "    @GetMapping(\"/base\")\n" +
                    "    public Result getBase64() {\n" +
                    "        return Result.success(InnerCaptchaUtil.getCaptcha());\n" +
                    "    }\n" +
                    "\n" +
                    "    @GetMapping(\"/verify\")\n" +
                    "    public Result verifyCode(@RequestParam(\"key\") String key,@RequestParam(\"captcha\") String code) {\n" +
                    "        return Result.success(InnerCaptchaUtil.verifyCaptcha(key, code));\n" +
                    "    }\n" +
                    "}\n";
    public static void generateController() throws IOException {
        String content = String.format(CLASS_TEMPLATE_CONTROLLER, LocalDate.now());
        File outputFile = new File(Easy.PROJECT_ABSOLUTE_URL + Easy.SRC_DIR + Easy.convertPackagePath(Easy.CONTROLLER_PACKAGE) + "/" + CONTROLLER_NAME + ".java");
        try (FileWriter writer = new FileWriter(outputFile)) {
            writer.write(content);
        }
    }
    public static void generate() throws IOException {
        Easy.initPackage(Easy.CONTROLLER_PACKAGE);
        Easy.initPackage(PACKAGE_NAME);
        generateMap();
        generateUtil();
        generateController();
    }

}
